package com.weifly.weistock.module.stockbill.impl;

import com.weifly.weistock.bo.MergeRecordResult;
import com.weifly.weistock.core.util.ConvertUtils;
import com.weifly.weistock.core.util.RecordUtils;
import com.weifly.weistock.core.util.WeistockUtils;
import com.weifly.weistock.module.stockbill.CalcStockContext;
import com.weifly.weistock.module.stockbill.StockBillConverter;
import com.weifly.weistock.module.stockbill.StockBillHoldService;
import com.weifly.weistock.module.stockbill.StockBillStoreService;
import com.weifly.weistock.module.stockbill.bo.GetStockRecordRequest;
import com.weifly.weistock.module.stockbill.bo.StockHoldSummaryBO;
import com.weifly.weistock.module.stockbill.bo.StockRecordBO;
import com.weifly.weistock.module.stockbill.bo.StockSummaryBO;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 * 股票交易记录管理服务实现
 *
 * @author weifly
 * @since 2020/01/15
 */
public class StockBillHoldServiceImpl implements StockBillHoldService {

    private SortedMap<String, StockSummaryBO> stockMap = new TreeMap<>(); // key有序的map

    private StockBillStoreService stockBillStoreService;

    public void setStockBillStoreService(StockBillStoreService stockBillStoreService) {
        this.stockBillStoreService = stockBillStoreService;
    }

    @Override
    public MergeRecordResult mergeRecordList(List<StockRecordBO> recordList) {
        MergeRecordResult result = new MergeRecordResult();
        if (recordList == null || recordList.isEmpty()) {
            return result;
        }

        Map<String, StockSummaryBO> modifyStockMap = new TreeMap<>(); // 被修改的股票集合
        result.setTotal(recordList.size());

        // 合并record到summary
        for (StockRecordBO recordBO : recordList) {
            ConvertUtils.checkEmpty(recordBO.getDate(), "发生日期不能为空");
            ConvertUtils.checkEmpty(recordBO.getStockCode(), "证券代码不能为空");
            StockSummaryBO summaryBO = this.loadStockSummary(recordBO, modifyStockMap);
            StockBillConverter.addRecordToSummary(summaryBO, recordBO, result);
        }

        for (StockSummaryBO summaryBO : modifyStockMap.values()) {
            // 交易记录排序
            RecordUtils.sortRecordList(summaryBO.getRecordList());
            // 计算盈亏
            this.calcOneStock(summaryBO);
            // 写入存储
            this.stockBillStoreService.saveStockSummary(summaryBO);
            // 替换缓存
            this.stockMap.put(summaryBO.getStockCode(), summaryBO);
        }

        return result;
    }

    private StockSummaryBO loadStockSummary(StockRecordBO recordBO, Map<String, StockSummaryBO> modifyStockMap) {
        StockSummaryBO summaryBO = modifyStockMap.get(recordBO.getStockCode());
        if (summaryBO == null) {
            // 从xml中加载
            summaryBO = this.stockBillStoreService.loadStockSummary(recordBO.getStockCode());
            if (summaryBO == null) {
                // 库中没有，新创建
                summaryBO = new StockSummaryBO();
                summaryBO.setStockCode(recordBO.getStockCode());
                summaryBO.setStockName(recordBO.getStockName());
            }
            modifyStockMap.put(recordBO.getStockCode(), summaryBO);
        }
        return summaryBO;
    }

    public void calcOneStock(StockSummaryBO summaryBO) {
        List<StockRecordBO> recordList = summaryBO.getRecordList();
        RecordUtils.clearRecordPair(recordList);

        CalcStockContext calcCtx = new CalcStockContext();
        for (int i = 0; i < recordList.size(); i++) {
            StockRecordBO currRecord = recordList.get(i);
            // 处理卖出记录
            if (StockBillConverter.isCloseRecord(currRecord)) {
                calcCtx.initRecord(currRecord);
                for (int j = i - 1; j >= 0; j--) {
                    StockRecordBO preRecord = recordList.get(j);
                    calcCtx.buildPair(preRecord);
                    if (calcCtx.getCurrTradeNumber() <= 0) {
                        // 完成配对
                        break;
                    }
                }
                calcCtx.finishRecord();
            }
        }

        // 计算统计信息
        double diffAmount = 0;
        double feeService = 0;
        double feeStamp = 0;
        Integer afterNumber = null;
        for (int i = 0; i < recordList.size(); i++) {
            StockRecordBO currRecord = recordList.get(i);
            if (currRecord.getDiffAmount() != null) {
                diffAmount = WeistockUtils.add(diffAmount, currRecord.getDiffAmount());
            }
            if (currRecord.getFeeService() != null) {
                feeService = WeistockUtils.add(feeService, currRecord.getFeeService());
            }
            if (currRecord.getFeeStamp() != null) {
                feeStamp = WeistockUtils.add(feeStamp, currRecord.getFeeStamp());
            }
            afterNumber = currRecord.getAfterNumber();
        }
        summaryBO.setDiffAmount(diffAmount);
        summaryBO.setFeeService(feeService);
        summaryBO.setFeeStamp(feeStamp);
        summaryBO.setAfterNumber(afterNumber);
    }

    @Override
    public List<StockSummaryBO> getStockList() {
        return new ArrayList<>(this.stockMap.values());
    }

    @Override
    public StockSummaryBO getStockSummary(String stockCode) {
        if (StringUtils.isBlank(stockCode)) {
            return null;
        }
        return this.stockMap.get(stockCode);
    }

    @Override
    public StockHoldSummaryBO getStockHold(String stockCode) {
        return StockBillConverter.convertToStockHoldSummaryBO(this.stockMap.get(stockCode));
    }

    @Override
    public void updateStockList(List<StockSummaryBO> stockList) {
        this.stockMap.clear();
        for (StockSummaryBO summaryDto : stockList) {
            this.stockMap.put(summaryDto.getStockCode(), summaryDto);
        }
    }

    @Override
    public List<StockRecordBO> getRecordList(GetStockRecordRequest queryRequest) {
        List<StockRecordBO> recordList = new ArrayList<>();
        if (StringUtils.isBlank(queryRequest.getStockCode())) {
            return recordList;
        }
        StockSummaryBO summaryDto = this.stockMap.get(queryRequest.getStockCode());
        if (summaryDto == null) {
            return recordList;
        }

        List<StockRecordBO> dtoList = summaryDto.getRecordList();
        int limit = queryRequest.getLimit();
        // 降序遍历
        for (int i = dtoList.size() - 1; i >= 0; i--) {
            StockRecordBO dto = dtoList.get(i);
            if (!this.filterRecord(dto, queryRequest)) {
                recordList.add(dto);
                if (recordList.size() >= limit) {
                    break;
                }
            }
        }
        return recordList;
    }

    // 需要过滤的记录，则返回true
    private boolean filterRecord(StockRecordBO recordBO, GetStockRecordRequest request) {
        // 日期、时间、委托编号过滤
        if (StringUtils.isNotBlank(request.getDate())
                && StringUtils.isNotBlank(request.getTime())
                && StringUtils.isNotBlank(request.getEntrust())) {
            int dataCompare = recordBO.getDate().compareTo(request.getDate());
            // 判断date
            if (dataCompare < 0) {
                // record date 小，不需要过滤
            } else if (dataCompare > 0) {
                return true; // record date 大，需要过滤
            } else {
                // 判断time
                int timeCompare = recordBO.getTime().compareTo(request.getTime());
                if (timeCompare < 0) {
                    // record time 小，不需要过滤
                } else if (timeCompare > 0) {
                    return true; // record time 大，需要过滤
                } else {
                    // 判断entrustCode
                    int entrustCodeCompare = recordBO.getEntrustCode().compareTo(request.getEntrust());
                    if (entrustCodeCompare >= 0) {
                        return true; // record entrustCode大，需要过滤
                    } else {
                        // record entrustCode小，不需要过滤
                    }
                }
            }
        }

        return false;
    }
}
